package com.osc.exam.error;

import com.osc.exam.base.BaseResponse;
import com.osc.exam.constant.GlobalConstant;
import org.apache.shiro.authz.UnauthorizedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

/**
 * spring boot rest exception handler.
 *
 * @author:
 * @since: 2020/6/16
 */
@RestControllerAdvice
public class CustomExceptionHandler {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    //@Value("${spring.servlet.multipart.max-file-size}")
    private String maxFileUploadSize;

    /**
     * 自定义异常
     *
     * @param e
     * @return ResponseEntity
     */
    @ExceptionHandler(value = CustomerException.class)
    public ResponseEntity<BaseResponse<Object>> handleCustomException(CustomerException e) {
        logger.error("请求异常:{}", e.getMessage());
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body(BaseResponse.result(GlobalConstant.FAIL, e.getMsg()));
    }

    /**
     * 数据库异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(DataIntegrityViolationException.class)
    public ResponseEntity<BaseResponse<Object>> handleDataIntegrityViolationException(
            DataIntegrityViolationException e) {
        logger.error("数据库异常", e);
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body(BaseResponse.result(GlobalConstant.FAIL, "请联系管理员!"));
    }

    /**
     * 数据库key重复
     *
     * @param e
     * @return
     */
    @ExceptionHandler(DuplicateKeyException.class)
    public ResponseEntity<BaseResponse<Object>> duplicateKeyException(DuplicateKeyException e) {
        logger.error("数据库key重复", e);
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body(BaseResponse.result(GlobalConstant.FAIL, "该企业配置已存在!"));
    }

    /**
     * 登陆异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(LoginException.class)
    public ResponseEntity<BaseResponse<Object>> handleLoginException(LoginException e) {
        logger.error("登陆异常:{}", e.getMsg());
        return ResponseEntity.status(HttpStatus.PRECONDITION_FAILED)
                .body(BaseResponse.result(GlobalConstant.FAIL, e.getMsg()));
    }

    /**
     * 超出最大上传文件大小
     *
     * @param e
     * @return
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public ResponseEntity<BaseResponse<Object>> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
        logger.error("上传异常", e);
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body(BaseResponse.result(GlobalConstant.FAIL, "上传文件最大不能超过" + maxFileUploadSize));
    }

    /**
     * 上传异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(UploadException.class)
    public ResponseEntity<BaseResponse<Object>> handleUploadException(UploadException e) {
        logger.error("上传异常", e);
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body(BaseResponse.result(GlobalConstant.FAIL, e.getMsg()));
    }

    /**
     * 请求参数有误
     *
     * @param e
     * @return
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseEntity<BaseResponse<Object>> httpMessageNotReadableException(HttpMessageNotReadableException e) {
        logger.error("请求参数有误", e);
        if (e.getMessage().contains("emoji")) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body(BaseResponse.result(GlobalConstant.FAIL, "请求参数不要带emoji"));
        }
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body(BaseResponse.result(GlobalConstant.FAIL, "请求参数有误"));
    }


    /**
     * 服务器异常
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(value = {Exception.class, RuntimeException.class})
    public ResponseEntity<BaseResponse<Object>> defaultErrorHandler(Exception ex) {
        logger.error("服务器异常", ex);
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(BaseResponse.result(GlobalConstant.FAIL, "服务器正忙,请稍后再试!"));
    }

    // 无权限时触发的异常
    @ExceptionHandler(UnauthorizedException.class)
    public ResponseEntity<BaseResponse<Object>> UnauthorizedExceptionHandler(UnauthorizedException ex){
        logger.error("您没有操作权限", ex);
        return ResponseEntity.status(HttpStatus.FORBIDDEN)
                .body(BaseResponse.result(GlobalConstant.FAIL, "您没有操作权限"));
    }



    @ExceptionHandler(BindException.class)
    public ResponseEntity<BaseResponse<Object>> bindExceptionHandler(BindException ex) {
        logger.error("[BindException]", ex);
        StringBuffer detailMessage = new StringBuffer();
        for (FieldError fieldError : ex.getBindingResult().getFieldErrors()) {
            if (detailMessage.length() > 0) {
                detailMessage.append(";");
            }
            detailMessage.append(fieldError.getField() + ":" + fieldError.getDefaultMessage());
        }
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body(BaseResponse.result(GlobalConstant.FAIL, detailMessage.toString()));
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<BaseResponse<Object>> bindExceptionHandler(MethodArgumentNotValidException ex) {
        logger.error("[MethodArgumentNotValidException]", ex);
        StringBuffer detailMessage = new StringBuffer();
        for (FieldError fieldError : ex.getBindingResult().getFieldErrors()) {
            if (detailMessage.length() > 0) {
                detailMessage.append(";");
            }
            detailMessage.append(fieldError.getField() + ":" + fieldError.getDefaultMessage());
        }
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(BaseResponse.result(GlobalConstant.FAIL, detailMessage.toString()));
    }
}
